package com.zatech.cgnci.project.controller;


import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zatech.cgnci.project.base.context.UserContext;
import com.zatech.cgnci.project.base.enums.ApprovalConfigEnum;
import com.zatech.cgnci.project.base.enums.BusinessScenariosEnum;
import com.zatech.cgnci.project.base.enums.OperationTypeEnum;
import com.zatech.cgnci.project.base.enums.ResponseCodeEnum;
import com.zatech.cgnci.project.base.exception.GlobalException;
import com.zatech.cgnci.project.base.utils.BeanUtils;
import com.zatech.cgnci.project.base.utils.ConvertUtils;
import com.zatech.cgnci.project.base.utils.DateUtils;
import com.zatech.cgnci.project.base.utils.VerifyUtils;
import com.zatech.cgnci.project.dto.*;
import com.zatech.cgnci.project.entity.CgnciBusinessInsuranceDO;
import com.zatech.cgnci.project.entity.CgnciEndorsementDO;
import com.zatech.cgnci.project.entity.UserEntity;
import com.zatech.cgnci.project.service.*;
import com.zatech.cgnci.project.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 批改主表 前端控制器
 * </p>
 *
 * @author Generator
 * @since 2024-12-17
 */
@RestController
@RequestMapping("/api/endorsement/divide-out")
@RequiredArgsConstructor
@Api(produces = "application/json", tags = "批改管理--分出批改api接口文档")
public class CgnciEndorsementDivideOutController {

    private final CgnciEndorsementService endorsementService;

    private final IApprovalService approvalService;

    private final CgnciBusinessInsuranceService cgnciBusinessInsuranceService;

    private final CgnciReinsuranceRiskService cgnciReinsuranceRiskService;

    private final CgnciReinsuranceRiskInsuredService cgnciReinsuranceRiskInsuredService;

    private final CgnciOperationLogsService cgnciOperationLogsService;

    private final CgnciCodeTypeService cgnciCodeTypeService;

    @PostMapping("/page")
    @ApiOperation(value = "分页列表查询")
    public IPage<CgnciEndorsementInsurancePageVO> page(@RequestBody CgnciEndorsementInsuranceQueryDTO queryDTO) {
        queryDTO.setBusinessType("3");
        return endorsementService.pageEndorsementInsurance(queryDTO);
    }

    @GetMapping("/detail")
    @ApiOperation(value = "详情")
    public CgnciEndorsementInsuranceVO detail(@RequestParam(value = "endorsementId") @NotNull(message = "endorsementId不能为空") Long endorsementId) {
        return endorsementService.detail(endorsementId, "3");
    }


    @PostMapping("/next/create")
    @ApiOperation(value = "新增分出合约批单录入")
    @Transactional(rollbackFor = Exception.class)
    public Long nextCreate(@RequestBody @Valid CgnciEndorsementInsuranceNextCreateDTO addCreateDTO) {
        // 获取当前登录用户
        UserEntity user = UserContext.getUser();

        // 校验原保单id
        CgnciBusinessInsuranceDO copyInsurance = cgnciBusinessInsuranceService.getById(addCreateDTO.getInsuranceId());
        if (VerifyUtils.isEmpty(copyInsurance)) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "请输入正确的合约编号");
        }

        if (!"1".equals(copyInsurance.getIsEffective()) && !"3".equals(copyInsurance.getStatus())) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "该合约不是已生效的状态，不允许批改");
        }

        // 校验批改生效日不得在保单保障期间外
        boolean isInRange = !addCreateDTO.getEffectiveDate().before(copyInsurance.getStartDate()) &&
                !addCreateDTO.getEffectiveDate().after(copyInsurance.getEndDate());
        if (!isInRange) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR,
                    "合约保障期间为{" + DateUtils.dateToString(copyInsurance.getStartDate(), DateUtils.FORMAT_3) + "}至" +
                            "{" + DateUtils.dateToString(copyInsurance.getEndDate(), DateUtils.FORMAT_3) + "}，批改生效日应在合约保障期间内");
        }

        CgnciEndorsementDO endorsementDO = ConvertUtils.convert(addCreateDTO, CgnciEndorsementDO.class);
        // 业务类型-分出合约
        endorsementDO.setBusinessType("3");
        endorsementDO.setBusinessId(copyInsurance.getInsuranceId());
        endorsementDO.setFormNo(copyInsurance.getFormNo());
        // E+承保年度+合约类型+0001
        // 合约类型：比例：P；非比例：N
        String businessNo;
        if ("1".equals(copyInsurance.getBusinessForm())) {
            businessNo = "P" + cgnciCodeTypeService.getBusinessNo("pdhybh-bl", "number");
        } else {
            businessNo = "N" + cgnciCodeTypeService.getBusinessNo("pdhybh-fbl", "number");
        }
        endorsementDO.setEndorsementNo("E" + copyInsurance.getBusinessYear() + businessNo);
        endorsementDO.setCreateUser(user.getNameAndCode());
        endorsementDO.setUpdateUser(user.getNameAndCode());
        // 保存批改信息
        endorsementService.save(endorsementDO);

        endorsementService.nextDivideOutCreate(addCreateDTO, endorsementDO.getEndorsementId());

        // 创建任务,绑定工作流formId. 并且关联工作台的跳转地址url以及参数
        ApprovalInfoVO approvalInfoVO = approvalService.create(FlowTaskCreateDTO.builder().approvalConfigGroupId(ApprovalConfigEnum.APPROVAL_CONFIG_015.getGroupId()).formId(String.valueOf(endorsementDO.getEndorsementId())).formNo(endorsementDO.getFormNo())
                .redirectionUrl(ApprovalConfigEnum.APPROVAL_CONFIG_015.getRedirectionUrl()).redirectionParam(String.valueOf(endorsementDO.getEndorsementId())).redirectionDesc(ApprovalConfigEnum.APPROVAL_CONFIG_015.getRedirectionDesc()).build());
        cgnciOperationLogsService.insertOperationLogs(
                String.valueOf(endorsementDO.getBusinessId()),
                BusinessScenariosEnum.POLICY.getCode(),
                OperationTypeEnum.SUBMIT_OUTGOING_CONTRACT_CHANGE.getCode(),
                "分出合约批改录入任务号：" + approvalInfoVO.getTaskId(),
                user.getNameAndCode()
        );
        return endorsementDO.getEndorsementId();
    }

    @PostMapping("/saveOrUpdate")
    @ApiOperation(value = "新增或者修改")
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdate(@RequestBody @Valid CgnciEndorsementInsuranceSaveOrUpdateDTO updateDTO) {
        // 修改批改信息
        endorsementService.updateEndorsementInsurance(updateDTO,"3");

        // 修改业务数据
        CgnciBusinessInsuranceSaveOrUpdateDTO businessInsuranceUpdateDTO = ConvertUtils.convert(updateDTO.getBusinessInsuranceUpdateDTO(), CgnciBusinessInsuranceSaveOrUpdateDTO.class);
        businessInsuranceUpdateDTO.setFlowTaskType(updateDTO.getFlowTaskType());
        cgnciBusinessInsuranceService.saveOrUpdateBusinessInsurance(businessInsuranceUpdateDTO, "3");

        // 提交审核
        if (VerifyUtils.isNotEmpty(updateDTO.getFlowTaskType()) && "submit".equals(updateDTO.getFlowTaskType())) {
            endorsementService.submit(FlowTaskSubmitDTO.builder().approvalInfoId(updateDTO.getApprovalInfoId()).formId(String.valueOf(String.valueOf(updateDTO.getEndorsementInsuranceDTO().getEndorsementId()))).build());
        }
    }

    @PostMapping("/approve")
    @ApiOperation(value = "审核流程任务")
    @Transactional(rollbackFor = Exception.class)
    public void approve(@RequestBody @Valid FlowTaskApprovalDTO flowTaskDTO) {
        endorsementService.approve(flowTaskDTO);
    }

    @GetMapping("/listBackNode")
    @ApiOperation(value = "获取退回流程节点")
    public List<ApprovalConfigVO> listBackNode(@RequestParam(value = "endorsementId") @NotNull(message = "endorsementId不能为空") Long endorsementId) {
        CgnciEndorsementDO endorsementDO = endorsementService.getById(endorsementId);
        return approvalService.listBackNode(String.valueOf(endorsementDO.getEndorsementId()), endorsementDO.getFormNo());
    }

    @PostMapping("/back")
    @ApiOperation(value = "退回流程任务")
    @Transactional(rollbackFor = Exception.class)
    public void back(@RequestBody @Valid FlowTaskBackDTO flowTaskDTO) {
        endorsementService.back(flowTaskDTO);
    }

    @GetMapping("/signOut")
    @ApiOperation(value = "注销")
    @Transactional(rollbackFor = Exception.class)
    public void signOut(@RequestParam(value = "endorsementId") @NotNull(message = "endorsementId不能为空") Long endorsementId) {
        endorsementService.signOut(endorsementId);
    }

    @GetMapping("/log")
    @ApiOperation(value = "获取操作日志")
    public List<ApprovalRecordVO> log(@RequestParam(value = "endorsementId") @NotNull(message = "endorsementId不能为空") Long endorsementId) {
        return endorsementService.log(endorsementId);
    }

    @GetMapping("/reinsuranceRisk/deleteById")
    @ApiOperation(value = "删除分入分出险种")
    @Transactional(rollbackFor = Exception.class)
    public void deleteReinsuranceRiskDetailById(@RequestParam(value = "reinsuranceRiskId") @ApiParam(value = "reinsuranceRiskId") Long reinsuranceRiskId) {
        cgnciReinsuranceRiskService.deleteReinsuranceRiskForDivideOut(reinsuranceRiskId);
    }

    @GetMapping("/reinsuranceRisk/deleteByIds")
    @ApiOperation(value = "批量删除分入分出险种")
    @Transactional(rollbackFor = Exception.class)
    public void deleteReinsuranceRiskDetailByIds(@RequestParam(value = "reinsuranceRiskIds") @ApiParam(value = "reinsuranceRiskIds") String reinsuranceRiskIds) {
        List<Long> idList = Arrays.stream(reinsuranceRiskIds.split(",")).map(Long::valueOf).collect(Collectors.toList());
        idList.forEach(cgnciReinsuranceRiskService::deleteReinsuranceRiskForDivideOut);
    }

    @GetMapping("/reinsuranceRiskInsured/deleteById")
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation(value = "删除分入分出险种标的")
    public void deleteReinsuranceRiskInsuredById(@RequestParam(value = "riskInsuredId") @ApiParam(value = "riskInsuredId") Long riskInsuredId) {
        cgnciReinsuranceRiskInsuredService.deleteReinsuranceRiskInsuredForDivideOut(riskInsuredId);
    }

    @GetMapping("/reinsuranceRiskInsured/deleteByIds")
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation(value = "批量删除分入分出险种标的")
    public void deleteReinsuranceRiskInsuredByIds(@RequestParam(value = "riskInsuredIds") @ApiParam(value = "riskInsuredIds") String riskInsuredIds) {
        List<Long> idList = Arrays.stream(riskInsuredIds.split(",")).map(Long::valueOf).collect(Collectors.toList());
        idList.forEach(cgnciReinsuranceRiskInsuredService::deleteReinsuranceRiskInsuredForDivideOut);
    }

}

